/**********************************Copyright (c)**********************************
**                       版权所有 (C), 2015-2020, 涂鸦科技
**
**                             http://www.tuya.com
**
*********************************************************************************/
/**
 * @file    system.c
 * @author  涂鸦综合协议开发组
 * @version v1.0.5
 * @date    2021.10.19
 * @brief   串口数据处理，用户无需关心该文件实现内容
 */

/****************************** 免责声明 ！！！ *******************************
由于MCU类型和编译环境多种多样，所以此代码仅供参考，用户请自行把控最终代码质量，
涂鸦不对MCU功能结果负责。
******************************************************************************/

#define SYSTEM_GLOBAL

#include "wifi.h"
#include <stdio.h>  // 用于sprintf函数

// 调试打印需要用到UART1,但Usart1.h会引入stm32f10x.h导致宏冲突
// 所以直接声明UART1_Printf函数,不include头文件
extern void UART1_Printf(char* fmt, ...);

extern const DOWNLOAD_CMD_S download_cmd[];
extern void all_data_for_wifi_test(void);                          //声明new_data_for_wifi_test函数
u16 firm_size;                                                      //升级包一包的大小
static u8 mcu_reset_state = FALSE;                                  //MCU复位状态标志：FALSE=未复位过, TRUE=已复位

//=============================================================================
// 涂鸦协议调试打印宏 - 通过宏开关控制
//=============================================================================
#ifdef TUYA_PROTOCOL_DEBUG
    #define TUYA_PRINTF(fmt, ...)   UART1_Printf("[TUYA] " fmt "\r\n", ##__VA_ARGS__)

    // 打印16进制数据 (改用十进制显示,因为UART1_Printf不支持%X格式)
    static void print_hex_data(const char *prefix, u8 *data, u16 len)
    {
        u16 i;
        UART1_Printf("%s[%d]: ", prefix, (int)len);
        for(i = 0; i < len; i++) {
            UART1_Printf("%d ", (int)data[i]);
            if((i + 1) % 16 == 0 && i != len - 1) {
                UART1_Printf("\r\n        ");  // 每16字节换行
            }
        }
        UART1_Printf("\r\n");
    }
#else
    #define TUYA_PRINTF(fmt, ...)
    #define print_hex_data(prefix, data, len)
#endif

/**
 * @brief  写wifi_uart字节
 * @param[in] {dest} 缓存区其实地址
 * @param[in] {byte} 写入字节值
 * @return 写入完成后的总长度
 */
u16 set_wifi_uart_byte(u16 dest, u8 byte)
{
    u8 *obj = (u8 *)wifi_uart_tx_buf + DATA_START + dest;

    *obj = byte;
    dest += 1;

    return dest;
}

/**
 * @brief  写wifi_uart_buffer
 * @param[in] {dest} 目标地址
 * @param[in] {src} 源地址
 * @param[in] {len} 数据长度
 * @return 写入结束的缓存地址
 */
u16 set_wifi_uart_buffer(u16 dest, u8 *src, u16 len)
{
    u8 *obj = (u8 *)wifi_uart_tx_buf + DATA_START + dest;

    my_memcpy(obj,src,len);

    dest += len;
    return dest;
}

/**
 * @brief  串口发送一段数据
 * @param[in] {in} 发送缓存指针
 * @param[in] {len} 数据发送长度
 * @return Null
 */
static void wifi_uart_write_data(u8 *in, u16 len)
{
    if((NULL == in) || (0 == len))
    {
        return;
    }

    while(len --)
    {
        uart_transmit_output(*in);
        in ++;
    }
}

/**
 * @brief  计算校验和
 * @param[in] {pack} 数据源指针
 * @param[in] {pack_len} 计算校验和长度
 * @return 校验和
 */
u8 get_check_sum(u8 *pack, u16 pack_len)
{
    u16 i;
    u8 check_sum = 0;

    for(i = 0; i < pack_len; i ++)
    {
        check_sum += *pack ++;
    }

    return check_sum;
}

/**
 * @brief  向wifi串口发送一帧数据
 * @param[in] {fr_type} 帧类型
 * @param[in] {len} 数据长度
 * @return Null
 */
void wifi_uart_write_frame(u8 fr_type, u16 len)
{
    u8 check_sum = 0;

    wifi_uart_tx_buf[HEAD_FIRST] = 0x55;
    wifi_uart_tx_buf[HEAD_SECOND] = 0xaa;
    wifi_uart_tx_buf[PROTOCOL_VERSION] = 0x03;  // 产品信息响应必须使用0x03版本号
    wifi_uart_tx_buf[FRAME_TYPE] = fr_type;
    wifi_uart_tx_buf[LENGTH_HIGH] = len >> 8;
    wifi_uart_tx_buf[LENGTH_LOW] = len & 0xff;

    len += PROTOCOL_HEAD;
    check_sum = get_check_sum((u8 *)wifi_uart_tx_buf, len - 1);
    wifi_uart_tx_buf[len - 1] = check_sum;

#ifdef TUYA_PROTOCOL_DEBUG
    // 打印发送的帧数据
    print_hex_data("TX", (u8 *)wifi_uart_tx_buf, len);
    TUYA_PRINTF("TX CMD: %d", (int)fr_type);
#endif

    //
    wifi_uart_write_data((u8 *)wifi_uart_tx_buf, len);
}

/**
 * @brief  产品信息上传
 * @param  Null
 * @return Null
 */
static void product_info_update(void)
{
    u8 length = 0;
    u8 str[32] = {0};

    // 基础字段：产品Key和MCU版本
    length = set_wifi_uart_buffer(length, "{\"p\":\"", my_strlen("{\"p\":\""));
    length = set_wifi_uart_buffer(length, (u8 *)PRODUCT_KEY, my_strlen((u8 *)PRODUCT_KEY));
    length = set_wifi_uart_buffer(length, "\",\"v\":\"", my_strlen("\",\"v\":\""));
    length = set_wifi_uart_buffer(length, (u8 *)MCU_VER, my_strlen((u8 *)MCU_VER));
    length = set_wifi_uart_buffer(length, "\",\"m\":", my_strlen("\",\"m\":"));

    // 配置模式字段 - 使用CONFIG_MODE宏替代硬编码的0
    my_memset(str, 0, sizeof(str));
    sprintf((char *)str, "%d", CONFIG_MODE);
    length = set_wifi_uart_buffer(length, str, my_strlen(str));

#ifdef CONFIG_MODE_DELAY_TIME
    my_memset(str, 0, sizeof(str));
    sprintf((char *)str, ",\"mt\":%d", CONFIG_MODE_DELAY_TIME);
    length = set_wifi_uart_buffer(length, str, my_strlen(str));
#endif

#ifdef CONFIG_MODE_CHOOSE
    my_memset(str, 0, sizeof(str));
    sprintf((char *)str, ",\"n\":%d", CONFIG_MODE_CHOOSE);
    length = set_wifi_uart_buffer(length, str, my_strlen(str));
#endif

#ifdef ENABLE_MODULE_IR_FUN
    my_memset(str, 0, sizeof(str));
    sprintf((char *)str, ",\"ir\":\"%d.%d\"", MODULE_IR_PIN_TX, MODULE_IR_PIN_RX);
    length = set_wifi_uart_buffer(length, str, my_strlen(str));
#endif

#ifdef LONG_CONN_LOWPOWER
    my_memset(str, 0, sizeof(str));
    sprintf((char *)str, ",\"low\":%d", LONG_CONN_LOWPOWER);
    length = set_wifi_uart_buffer(length, str, my_strlen(str));
#endif

    // 结束字符
    length = set_wifi_uart_buffer(length, "}", my_strlen("}"));

    wifi_uart_write_frame(PRODUCT_INFO_CMD, length);
}

/**
 * @brief  心跳包检测
 * @param  Null
 * @return Null
 */
static void heat_beat_check(void)
{
    u8 length = 0;

    if(FALSE == mcu_reset_state) {
        length = set_wifi_uart_byte(length, FALSE);                 //上电第一次心跳回复00
        mcu_reset_state = TRUE;
    } else {
        length = set_wifi_uart_byte(length, TRUE);                  //上电第二次及以后心跳回复01
    }

    wifi_uart_write_frame(HEARTBEAT_CMD, length);
}

/**
 * @brief  MCU查询MCU和WiFi的工作模式
 * @param  Null
 * @return Null
 */
static void get_mcu_wifi_mode(void)
{
    u8 length = 0;

#ifdef WIFI_CONTROL_SELF_MODE                                       //模组自处理模式
    length = set_wifi_uart_byte(length, WF_STATE_KEY);
    length = set_wifi_uart_byte(length, WF_RESERT_KEY);
#else
    //No need to process data
#endif

    wifi_uart_write_frame(WIFI_MODE_CMD, length);
}

/**
 * @brief  获取制定DPID在数组中的序号
 * @param[in] {dpid} dpid
 * @return dp序号
 */
static u8 get_dowmload_dpid_index(u8 dpid)
{
    u8 index;
    u8 total = get_download_cmd_total();

    for(index = 0; index < total; index ++)
    {
        if(download_cmd[index].dp_id == dpid)
        {
            break;
        }
    }

    return index;
}

/**
 * @brief  下发数据处理
 * @param[in] {value} 下发数据源指针
 * @return 返回数据处理结果
 */
static u8 data_point_handle(const u8 value[])
{
    u8 dp_id,index;
    u8 dp_type;
    u8 ret;
    u16 dp_len;

    dp_id = value[0];
    dp_type = value[1];
    dp_len = value[2] * 0x100;
    dp_len += value[3];

    index = get_dowmload_dpid_index(dp_id);

    if(dp_type != download_cmd[index].dp_type)
    {
        //错误提示
        return FALSE;
    }
    else
    {
        ret = dp_download_handle(dp_id,value + 4,dp_len);
    }

    return ret;
}

/**
 * @brief  数据帧处理
 * @param[in] {offset} 数据起始位
 * @return Null
 */
void data_handle(u16 offset)
{
#ifdef SUPPORT_MCU_FIRM_UPDATE
    u8 *firmware_addr;
    static u32 firm_length;                                             //MCU升级文件长度
    static u8 firm_update_flag;                                        //MCU升级标志
    u32 dp_len;
    u8 firm_flag;                                                      //升级包大小标志
#else
    u16 dp_len;
#endif
    u8 ret;
    u16 i,total_len;
    u8 cmd_type = wifi_data_process_buf[offset + FRAME_TYPE];
    u16 cmd_data_len = wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100 + wifi_data_process_buf[offset + LENGTH_LOW];
    u8 result;
    u8 dp_num;

#ifdef TUYA_PROTOCOL_DEBUG
    // 打印接收到的完整帧数据
    u16 frame_len = wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100 + wifi_data_process_buf[offset + LENGTH_LOW] + PROTOCOL_HEAD;
    print_hex_data("RX", wifi_data_process_buf + offset, frame_len);

    // 打印命令类型 (简化:只打印数字,避免格式化字符串问题)
    UART1_Printf("[TUYA] RX CMD: ");
    UART1_Printf("%d", (int)cmd_type);
    UART1_Printf(" (");
    // 根据命令类型打印名称
    if(cmd_type == HEARTBEAT_CMD) UART1_Printf("HEARTBEAT");
    else if(cmd_type == PRODUCT_INFO_CMD) UART1_Printf("PRODUCT_INFO");
    else if(cmd_type == WIFI_MODE_CMD) UART1_Printf("WIFI_MODE");
    else if(cmd_type == WIFI_STATE_CMD) UART1_Printf("WIFI_STATE");
    else if(cmd_type == WIFI_RESET_CMD) UART1_Printf("WIFI_RESET");
    else if(cmd_type == WIFI_RESET_MODE_CMD) UART1_Printf("WIFI_RESET_MODE");
    else if(cmd_type == STATE_DOWNLOAD_CMD) UART1_Printf("STATE_DOWNLOAD");
    else if(cmd_type == STATE_UPLOAD_CMD) UART1_Printf("STATE_UPLOAD");
    else if(cmd_type == DATA_SYNC_CMD) UART1_Printf("DATA_SYNC");
    else if(cmd_type == STATE_UPLOAD_SYNC_RESP_CMD) UART1_Printf("STATE_UPLOAD_SYNC_RESP");
    else if(cmd_type == STATE_RC_UPLOAD_CMD) UART1_Printf("STATE_RC_UPLOAD");
    else if(cmd_type == DEVICE_CAPABILITY_CMD) UART1_Printf("DEVICE_CAPABILITY");
    else if(cmd_type == WIFI_UPDATE_CMD) UART1_Printf("WIFI_UPDATE");
    else if(cmd_type == ROUTE_RSSI_CMD) UART1_Printf("ROUTE_RSSI");
    else if(cmd_type == REQUEST_MCU_UG_CMD) UART1_Printf("REQUEST_MCU_UG");
    else if(cmd_type == UPDATE_START_CMD) UART1_Printf("UPDATE_START");
    else if(cmd_type == UPDATE_TRANS_CMD) UART1_Printf("UPDATE_TRANS");
    else if(cmd_type == GET_DP_CACHE_CMD) UART1_Printf("GET_DP_CACHE");
    else UART1_Printf("UNKNOWN");
    UART1_Printf(")\r\n");
#endif

    switch(cmd_type)
    {
        case HEARTBEAT_CMD:                                   //心跳包
            heat_beat_check();
        break;

        case PRODUCT_INFO_CMD:                                //产品信息
            product_info_update();
        break;

#ifndef WIFI_CONTROL_SELF_MODE
        case WIFI_STATE_CMD:                                  //报告Wi-Fi工作状态指令
            wifi_work_state = wifi_data_process_buf[offset + DATA_START];     //查询联网状态值
#ifdef TUYA_PROTOCOL_DEBUG
            UART1_Printf("[TUYA] WiFi State: ");
            UART1_Printf("%d", (int)wifi_work_state);
            UART1_Printf(" (");
            if(wifi_work_state == 0) UART1_Printf("SmartConfig");
            else if(wifi_work_state == 1) UART1_Printf("AP");
            else if(wifi_work_state == 2) UART1_Printf("WiFi_Not_Conn");
            else if(wifi_work_state == 3) UART1_Printf("WiFi_Conn");
            else if(wifi_work_state == 4) UART1_Printf("Cloud_Conn");
            else if(wifi_work_state == 5) UART1_Printf("LowPower");
            else UART1_Printf("Unknown");
            UART1_Printf(")\r\n");
#endif
            wifi_uart_write_frame(WIFI_STATE_CMD, 0);  // 回复WiFi状态查询
        break;

        case WIFI_RESET_CMD:                                  //重置wifi
            // 如果有数据，读取并同步重置后的状态到本地
            if(cmd_data_len > 0) 
            {
                // 读取WiFi模块的新状态（重置后的状态值）
                u8 new_state = wifi_data_process_buf[offset + DATA_START];

                // 同步到本地状态变量
                wifi_work_state = new_state;

#ifdef TUYA_PROTOCOL_DEBUG
                UART1_Printf("[TUYA] WiFi Reset - New State: ");
                UART1_Printf("%d", (int)new_state);
                UART1_Printf(" (");
                if(new_state == 0) UART1_Printf("SmartConfig");
                else if(new_state == 1) UART1_Printf("AP");
                else if(new_state == 2) UART1_Printf("WiFi_Not_Conn");
                else if(new_state == 3) UART1_Printf("WiFi_Conn");
                else if(new_state == 4) UART1_Printf("Cloud_Conn");
                else if(new_state == 5) UART1_Printf("LowPower");
                else UART1_Printf("Unknown");
                UART1_Printf(")\r\n");
#endif

                // 回复 ACK 确认收到
                wifi_uart_write_frame(WIFI_RESET_CMD, 0);
            }
#ifndef WIFI_CONTROL_SELF_MODE
            // 更新本地状态标志
            reset_wifi_flag = RESET_WIFI_SUCCESS;
#endif
        break;

        case WIFI_MODE_CMD:                                   //查询模组工作模式指令
            get_mcu_wifi_mode();
        break;
#endif

        case STATE_DOWNLOAD_CMD:                              //状态下发（0x06）
            // WiFi模组下发DP命令给MCU执行
            total_len = wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100;
            total_len += wifi_data_process_buf[offset + LENGTH_LOW];

            for(i = 0;i < total_len;)
            {
                dp_len = wifi_data_process_buf[offset + DATA_START + i + 2] * 0x100;
                dp_len += wifi_data_process_buf[offset + DATA_START + i + 3];
                //
                ret = data_point_handle((u8 *)wifi_data_process_buf + offset + DATA_START + i);

                if(SUCCESS == ret)
                {
                    //成功提示
                }
                else
                {
                    //错误提示
                }

                i += (dp_len + 4);
            }

        break;

        case DATA_SYNC_CMD:                                   //下发数据同步指令（0x08）
            // WiFi模块请求MCU上报所有状态
            // MCU调用all_data_update()函数上报所有DP状态，用于面板同步设备状态
            all_data_update();
        break;

        // 注意：STATE_UPLOAD_CMD (0x07) 是MCU发送的命令，不是模组接收
        // 模组接收0x06/0x07作为数据下发命令，特定功能由子命令标识

#ifdef WIFI_MODULE_UPDATE
        case WIFI_UPDATE_CMD:                                 //请求WIFI模块固件升级
            qur_module_ug_result(wifi_data_process_buf[offset + DATA_START]);
        break;
#endif

#ifdef WIFI_QUERY_ROUTE_RSSI
        case ROUTE_RSSI_CMD:                                  //查询当前连接路由器信号强度
            router_strenth_result(wifi_data_process_buf[offset + DATA_START],wifi_data_process_buf[offset + DATA_START + 1]);
        break;
#endif
  
#ifdef SUPPORT_MCU_FIRM_UPDATE
        case REQUEST_MCU_UG_CMD:                              //请求mcu固件升级
            qur_ug_result(wifi_data_process_buf[offset + DATA_START]);
        break;

        case UPDATE_START_CMD:                                //升级开始
            //获取升级包大小全局变量
            firm_flag = PACKAGE_SIZE;
            if(firm_flag == 0) {
                firm_size = 256;
            }else if(firm_flag == 1) {
                firm_size = 512;
            }else if(firm_flag == 2) { 
                firm_size = 1024;
            }

            firm_length = wifi_data_process_buf[offset + DATA_START];
            firm_length <<= 8;
            firm_length |= wifi_data_process_buf[offset + DATA_START + 1];
            firm_length <<= 8;
            firm_length |= wifi_data_process_buf[offset + DATA_START + 2];
            firm_length <<= 8;
            firm_length |= wifi_data_process_buf[offset + DATA_START + 3];

            upgrade_package_choose(PACKAGE_SIZE);
            firm_update_flag = UPDATE_START_CMD;
        break;
  
        case UPDATE_TRANS_CMD:                                //升级传输
            if(firm_update_flag == UPDATE_START_CMD)
            {
                //停止一切数据上报
                stop_update_flag = ENABLE;

                total_len = wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100;
                total_len += wifi_data_process_buf[offset + LENGTH_LOW];

                dp_len = wifi_data_process_buf[offset + DATA_START];
                dp_len <<= 8;
                dp_len |= wifi_data_process_buf[offset + DATA_START + 1];
                dp_len <<= 8;
                dp_len |= wifi_data_process_buf[offset + DATA_START + 2];
                dp_len <<= 8;
                dp_len |= wifi_data_process_buf[offset + DATA_START + 3];

                firmware_addr = (u8 *)wifi_data_process_buf;
                firmware_addr += (offset + DATA_START + 4);

                if((total_len == 4) && (dp_len == firm_length))
                {
                    //最后一包
                    ret = mcu_firm_update_handle(firmware_addr,dp_len,0);
                  
                    firm_update_flag = 0;
                }
                else if((total_len - 4) <= firm_size)
                {
                    ret = mcu_firm_update_handle(firmware_addr,dp_len,total_len - 4);
                }
                else
                {
                    firm_update_flag = 0;
                    ret = ERROR;
                }

                if(ret == SUCCESS)
                {
                    wifi_uart_write_frame(UPDATE_TRANS_CMD,0);
                }
                //恢复一切数据上报
                stop_update_flag = DISABLE;    
            }
        break;
#endif

        case STATE_UPLOAD_SYNC_RESP_CMD:                       //状态上报（同步）响应（0x23）
            // 模组返回对MCU同步上报(0x22)的响应
            result = wifi_data_process_buf[offset + DATA_START];
            if(result == 0x00) {
                // 上报成功
            } else if(result == 0x01) {
                // 上报失败
            }
        break;

        case STATE_RC_UPLOAD_CMD:                              //状态上报（记录型DP）（0x34）
            // 模组返回对MCU记录型上报(0x34)的响应
            result = wifi_data_process_buf[offset + DATA_START];
            if(result == 0x0b) {
                // 子命令标识
                u8 status = wifi_data_process_buf[offset + DATA_START + 1];
                if(status == 0x00) {
                    // 上报成功
                } else {
                    // 上报失败
                }
            }
        break;

#ifdef DO_CACHE_SUPPORT
        case GET_DP_CACHE_CMD:                              //获取dp缓存指令
            total_len = wifi_data_process_buf[offset + LENGTH_HIGH] * 0x100;
            total_len += wifi_data_process_buf[offset + LENGTH_LOW];

            result = wifi_data_process_buf[offset + DATA_START]; //获取指令成功标志
            if(result == 0) {     //获取指令失败

            }else {               //获取指令成功
                dp_num = wifi_data_process_buf[offset + DATA_START + 1];//获取到的dp数量

                for(i = 2;i < total_len;)
                {
                    dp_len = wifi_data_process_buf[offset + DATA_START + i + 2] * 0x100; //value的字节数
                    dp_len += wifi_data_process_buf[offset + DATA_START + i + 3];

                    //处理状态数据单元
                    ret = data_point_handle((u8 *)wifi_data_process_buf + offset + DATA_START + i);

                    if(SUCCESS == ret)
                    {
                        //成功提示
                    }
                    else
                    {
                        //错误提示
                    }

                    i += (dp_len + 4);  //dp_len(value) + len(2) + type(1) + dpid(1)
                }
            }
        break;
#endif

        default:
        break;
    }
}

/**
 * @brief  判断uart接收缓冲区是否有数据
 * @param  无
 * @return 是否有数据
 */
u8 get_queue_total_data(void)
{
    if(queue_in != queue_out)
        return 1;
    else
        return 0;
}

/**
 * @brief  读取队列1字节数据
 * @param  无
 * @return 读到的数据
 */
u8 Queue_Read_Byte(void)
{
  u8 value;
  
  if(queue_out != queue_in)
  {
    //有数据
    if(queue_out >= (u8 *)(wifi_uart_rx_buf + sizeof(wifi_uart_rx_buf)))
    {
      //数据已经到末尾
      queue_out = (u8 *)(wifi_uart_rx_buf);
    }
    
    value = *queue_out ++;   
  }
  
  return value;
}

